package de.krecher.zmpp;

import java.io.File;
import java.io.FileInputStream;

import org.zmpp.ExecutionControl;
import org.zmpp.base.DefaultMemory;
import org.zmpp.encoding.DefaultAccentTable;
import org.zmpp.encoding.IZsciiEncoding;
import org.zmpp.encoding.ZsciiEncoding;
import org.zmpp.iff.FormChunk;
import org.zmpp.iff.WritableFormChunk;
import org.zmpp.vm.MachineRunState;
import org.zmpp.vm.PortableGameState;
import org.zmpp.vm.SaveGameDataStore;
import org.zmpp.vm.MachineFactory.MachineInitStruct;
import org.zmpp.windowing.AnnotatedText;
import org.zmpp.windowing.BufferedScreenModel;

import com.sun.org.apache.bcel.internal.ExceptionConstants;

public class Main {

	public static void main(String[] args) {
		File storyFile = new File("resource/minizork.z3");
		FileInputStream storyFileStream = null;
		try {
			storyFileStream = new FileInputStream(storyFile);
			MachineInitStruct initStruct = new MachineInitStruct();
			if (storyFile.getName().endsWith("zblorb")) {
				initStruct.blorbFile = storyFileStream;
			} else {
				initStruct.storyFile = storyFileStream;
			}
			// initStruct.nativeImageFactory = new AwtImageFactory();
			// initStruct.saveGameDataStore = new
			// FileSaveGameDataStore(zmppFrame);
			// initStruct.ioSystem = zmppFrame;
			// zmppFrame.getScreenModelView().startGame(initStruct);

			BufferedScreenModel screenModel = new BufferedScreenModel();
			FileInputStream fis = new FileInputStream(storyFile);
			byte[] data = new byte[fis.available()];
			fis.read(data);
			fis.close();

			screenModel.init(new DefaultMemory(data), new ZsciiEncoding(new DefaultAccentTable()));

			initStruct.saveGameDataStore = new MemorySaveGameDataStore();
			initStruct.screenModel = screenModel;
			initStruct.ioSystem = new IOSystemTextBased();
			initStruct.ioSystem.getTranscriptWriter();

			ExecutionControl executionControl = new ExecutionControl(initStruct);
			MachineRunState runState = executionControl.run();

			for (AnnotatedText text : screenModel.getLowerBuffer()) {
				System.out.println(text.getText().replaceAll(">", ""));
			}

			executionControl.resumeWithInput(new String("open mailbox".getBytes(), "UTF-8"));

			for (AnnotatedText text : screenModel.getLowerBuffer()) {
				System.out.println(text.getText().replaceAll(">", ""));
			}

			int pc = executionControl.getMachine().getPC();
			
			executionControl.getMachine().save(pc+1);
			
			executionControl.getMachine().reset();
			executionControl.getMachine().setRunState(MachineRunState.STOPPED);
			PortableGameState gameState = executionControl.getMachine().restore();
//			gameState.transferStateToMachine(executionControl.getMachine());
			executionControl.getMachine().setRunState(MachineRunState.RUNNING);
			executionControl.getMachine().incrementPC(3);
			executionControl.run();
			
			executionControl.resumeWithInput(new String("read leaflet".getBytes(), "UTF-8"));
			
			for (AnnotatedText text : screenModel.getLowerBuffer()) {
				System.out.println(text.getText().replaceAll(">", ""));
			}
			
			System.out.println();

		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (storyFileStream != null) {
				try {
					storyFileStream.close();
				} catch (Exception ioex) {
				}
			}
		}

	}

	public static class MemorySaveGameDataStore implements SaveGameDataStore {

		private WritableFormChunk savegame;

		public MemorySaveGameDataStore() {
			// TODO Auto-generated constructor stub
		}

		/** {@inheritDoc} */
		public boolean saveFormChunk(WritableFormChunk formchunk) {
			savegame = formchunk;
			return true;
		}

		/** {@inheritDoc} */
		public FormChunk retrieveFormChunk() {
			return savegame;
		}
	}
}
